﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Nirvana
{
    /// <summary>
    /// 用于管理skinmesh模型合并后的纹理合并数据缓存，提升性能，避免频繁合并纹理
    /// </summary>
    public sealed class TextureCombiner : Singleton<TextureCombiner>
    {
        private struct TextureWeakRef
        {
            public WeakReference weakRef;
            public Rect[] rects;
            public TextureWeakRef(Texture2D texture2D,Rect[] rect)
            {
                this.weakRef = new WeakReference(texture2D);
                this.rects = rect;
            }
        }

        private Dictionary<List<string>, TextureWeakRef> textureMap = new Dictionary<List<string>, TextureWeakRef>();
        private List<string> texturenamelist = new List<string>();
        public void Combine(Texture2D[] textures,out Texture2D atlas,out Rect[] rects)
        {
            foreach (Texture2D texture2D in textures)
            {
                this.texturenamelist.Add(texture2D.name);
            }
            this.texturenamelist.Sort();
            TextureWeakRef textureWeakRef;
            if(this.textureMap.TryGetValue(this.texturenamelist,out textureWeakRef))
            {
                if (textureWeakRef.weakRef.IsAlive)
                {
                    atlas = (Texture2D)textureWeakRef.weakRef.Target;
                    rects = textureWeakRef.rects;
                    this.texturenamelist.Clear();
                    return;
                }
                this.textureMap.Remove(this.texturenamelist);
            }

            var t = textures[0];
            atlas = new Texture2D(0, 0, t.format, t.mipmapCount > 0);
            atlas.name = "Combined Atlas";
            atlas.hideFlags = HideFlags.DontSave;
            rects = atlas.PackTextures(textures, 0, 4096, true);
            if (atlas.width > 2048 || atlas.height > 2048)
            {
                Debug.LogWarning(string.Concat(new object[]
                {
                    "The atlas is too large: ",
                    atlas.width,
                    ", ",
                    atlas.height
                }));
            }
            this.textureMap.Add(this.texturenamelist, new TextureWeakRef(atlas, rects));
            this.texturenamelist.Clear();
        }


    }
}

